﻿using Microsoft.Office.Interop.Word;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace OfficeMiddlewareCore
{
    public class WordHelper
    {
        private WordHelper()
        {
        }

        private static WordHelper _wordHelper;
        public static WordHelper Instance
        {
            get
            {
                if (_wordHelper == null)
                {
                    _wordHelper = new WordHelper();
                }
                return _wordHelper;
            }
        }
        public void OpenOnly(object filePath)
        {
            var wordApp = new Application
            {
                Visible = true
            };
            wordApp.Documents.Open(ref filePath);
        }

        /// <summary>
        /// 打开word文档
        /// </summary>
        /// <param name="filePath">文档路径</param>
        /// <returns></returns>
        public Tuple<Application, Document> Open(object filePath, bool isReadOnly = false)
        {
            try
            {
                var sw = new Stopwatch();
                sw.Start();

                var wordApp = new Application
                {
                    Visible = true
                };
                sw.Stop();
                LogHelper.Info($"word启动耗时:{sw.Elapsed}");
                sw.Restart();
                //  wordApp.ShowWindowsInTaskbar = true;
                var doc = wordApp.Documents.Open(ref filePath);
                DocumentConfig(doc);
                sw.Stop();
                LogHelper.Info($"word打开文档耗时:{sw.Elapsed}");
                sw.Restart();
                OpenType(doc, isReadOnly);
                sw.Stop();
                LogHelper.Info($"word设置参数耗时:{sw.Elapsed}");
                return new Tuple<Application, Document>(wordApp, doc);
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex.Message, ex);
                throw new CoreException(CoreResponseStatus.打开Word失败, "打开Word失败");
            }
        }

        private void OpenType(Document doc, bool isReadOnly)
        {
            if (isReadOnly)
            {
                if (doc.ProtectionType != WdProtectionType.wdAllowOnlyComments)
                    doc.Protect(WdProtectionType.wdAllowOnlyComments);
            }
            else
            {
                try
                {
                    if (doc.ProtectionType != WdProtectionType.wdNoProtection)
                    {
                        doc.Unprotect();
                    }
                    doc.Protect(WdProtectionType.wdNoProtection);
                }
                catch (Exception)
                {
                }
            }
        }

        private void DocumentConfig(Document document)
        {
            document.SpellingChecked = false;
            document.ShowSpellingErrors = false;
        }
        public string MergeDocument(List<string> files)
        {
            var app = new Application() { Visible = false };
            try
            {
                if (files.Count > 0)
                {
                    var mainDoc = app.Documents.Open(files[0]);
                    OpenType(mainDoc, false);

                    for (int i = 1; i < files.Count; i++)
                    {
                        var doc = app.Documents.Open(files[i]);
                        doc.Content.Copy();
                        Thread.Sleep(100);
                        mainDoc.Range(mainDoc.Content.End - 1, End: mainDoc.Content.End - 1).Paste();
                        doc.Close(false);
                    }
                    mainDoc.Save();
                    return files[0];
                }
                return null;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                app.Quit();
            }
        }

        /// <summary>
        /// 合并word文档
        /// </summary>
        /// <param name="body">正文文件路径</param>
        /// <param name="head">头部文件路径</param>
        /// <param name="end">尾部文件路径</param>
        /// <param name="copyHeader">复制页眉</param>
        public Tuple<Application, Document> Merge(string body, string head, string end, bool copyHeader = false)
        {
            var app = new Application() { Visible = false };
            //var headApp = new Application() { Visible = false };
            //var endApp = new Application() { Visible = false };
            try
            {


                var bodyDoc = app.Documents.Open(body);
                OpenType(bodyDoc, false);

                DocumentConfig(bodyDoc);
                var headDoc = app.Documents.Open(head);
                DocumentConfig(headDoc);
                if (headDoc.Content.StoryLength > 0)
                {
                    headDoc.Content.Copy();
                    Thread.Sleep(100);
                    bodyDoc.Range(bodyDoc.Content.Start, bodyDoc.Content.Start).Paste();
                }


                //if (headDoc.PageSetup.TopMargin < 1584)
                //{
                //    bodyDoc.PageSetup.TopMargin = headDoc.PageSetup.TopMargin;
                //}
                if (copyHeader)
                {
                    var bodySection = bodyDoc.Sections[1];
                    var headerSection = headDoc.Sections[1];

                    bodySection.PageSetup.DifferentFirstPageHeaderFooter = headerSection.PageSetup.DifferentFirstPageHeaderFooter;
                    bodySection.PageSetup.OddAndEvenPagesHeaderFooter = headerSection.PageSetup.OddAndEvenPagesHeaderFooter;
                    bodySection.PageSetup.TopMargin = headerSection.PageSetup.TopMargin;
                    bodySection.PageSetup.BottomMargin = headerSection.PageSetup.BottomMargin;
                    bodySection.PageSetup.LeftMargin = headerSection.PageSetup.LeftMargin;
                    bodySection.PageSetup.RightMargin = headerSection.PageSetup.RightMargin;
                    bodySection.PageSetup.HeaderDistance = headerSection.PageSetup.HeaderDistance;


                    HeaderFooter bodyHeader = bodySection.Headers[WdHeaderFooterIndex.wdHeaderFooterPrimary];
                    HeaderFooter headerHeader = headerSection.Headers[WdHeaderFooterIndex.wdHeaderFooterPrimary];
                    //bodyHeader.Range.ParagraphFormat.Borders[WdBorderType.wdBorderBottom].LineStyle = headerHeader.Range.ParagraphFormat.Borders[WdBorderType.wdBorderBottom].LineStyle;

                    //清除默认表头
                    if (bodyHeader.Exists)
                    {
                        // bodyHeader.Range.Delete();
                    }
                    if (headerHeader.Exists)
                    {
                        headerHeader.Range.Copy();
                        bodyHeader.Range.PasteAndFormat(WdRecoveryType.wdFormatOriginalFormatting);
                        bodyHeader.Range.ParagraphFormat.Borders[WdBorderType.wdBorderBottom].LineStyle = headerHeader.Range.ParagraphFormat.Borders[WdBorderType.wdBorderBottom].LineStyle;
                        bodyHeader.Range.ParagraphFormat.Borders[WdBorderType.wdBorderBottom].Color = headerHeader.Range.ParagraphFormat.Borders[WdBorderType.wdBorderBottom].Color;
                        bodyHeader.Range.ParagraphFormat.Borders[WdBorderType.wdBorderBottom].LineWidth = headerHeader.Range.ParagraphFormat.Borders[WdBorderType.wdBorderBottom].LineWidth;
                    }
                }
                headDoc.Close(false);
                //headApp.Quit(false);
                DeleteFile(head);

                var endDoc = app.Documents.Open(end);
                DocumentConfig(endDoc);
                if (endDoc.Content.StoryLength > 0)
                {
                    endDoc.Content.Copy();
                    Thread.Sleep(100);
                    bodyDoc.Range(bodyDoc.Content.End - 1, bodyDoc.Content.End - 1).Paste();
                }

                endDoc.Close(false);
                // endApp.Quit(false);

                //app.Visible = true;
                // app.ShowWindowsInTaskbar = true;
                DeleteFile(end);

                bodyDoc.Activate();
                bodyDoc.Save();
                return new Tuple<Application, Document>(app, bodyDoc);
            }
            catch (Exception ex)
            {
                try
                {
                    app.Quit(false);

                }
                catch (Exception)
                {

                }
                throw ex;
            }
        }

        void DeleteFile(string fileName)
        {
            ThreadPool.QueueUserWorkItem(state =>
            {
                var file = state.ToString();
                Thread.Sleep(1000);
                try
                {
                    File.Delete(file);
                }
                catch (Exception)
                {

                }
            }, fileName);
        }

        public void Replace(Document doc, Dictionary<string, string> replaceDic)
        {
            if (replaceDic == null) return;
            try
            {
                foreach (string key in replaceDic.Keys)
                {
                    doc.Application.Selection.Find.Execute(
                        FindText: key,
                        MatchCase: false,
                       ReplaceWith: replaceDic[key],
                       Replace: WdReplace.wdReplaceAll);
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex.Message, ex);
            }
            doc.Save();
        }
    }
}
